///*
// * Copyright 2004-2010 the original author or authors.
// *
// * Licensed under the Apache License, Version 2.0 (the "License");
// * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// *
// *      http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// */
//package org.springframework.security.taglibs.authz;
//
//import java.io.IOException;
//import java.util.Map;
//
//import javax.servlet.FilterChain;
//import javax.servlet.ServletContext;
//import javax.servlet.ServletException;
//import javax.servlet.ServletRequest;
//import javax.servlet.ServletResponse;
//import javax.servlet.http.HttpServletRequest;
//
//import org.springframework.context.ApplicationContext;
//import org.springframework.core.GenericTypeResolver;
//import org.springframework.expression.EvaluationContext;
//import org.springframework.expression.Expression;
//import org.springframework.expression.ParseException;
//import org.springframework.security.access.expression.ExpressionUtils;
//import org.springframework.security.access.expression.SecurityExpressionHandler;
//import org.springframework.security.core.Authentication;
//import org.springframework.security.core.context.SecurityContextHolder;
//import org.springframework.security.web.FilterInvocation;
//import org.springframework.security.web.WebAttributes;
//import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
//import org.springframework.security.web.context.support.SecurityWebApplicationContextUtils;
//import org.springframework.util.StringUtils;
//import org.springframework.web.servlet.FrameworkServlet;
//
///**
// * A base class for an &lt;authorize&gt; tag that is independent of the tag rendering
// * technology (JSP, Facelets). It treats tag attributes as simple strings rather than
// * strings that may contain expressions with the exception of the "access" attribute,
// * which is always expected to contain a Spring EL expression.
// * <p>
// * Subclasses are expected to extract tag attribute values from the specific rendering
// * technology, evaluate them as expressions if necessary, and set the String-based
// * attributes of this class.
// *
// * @author Francois Beausoleil
// * @author Luke Taylor
// * @author Rossen Stoyanchev
// * @author Rob Winch
// * @since 3.1.0
// */
//public abstract class AbstractAuthorizeTag {
//	private String access;
//	private String url;
//	private String method = "GET";
//
//	/**
//	 * This method allows subclasses to provide a way to access the ServletRequest
//	 * according to the rendering technology.
//	 */
//	protected abstract ServletRequest getRequest();
//
//	/**
//	 * This method allows subclasses to provide a way to access the ServletResponse
//	 * according to the rendering technology.
//	 */
//	protected abstract ServletResponse getResponse();
//
//	/**
//	 * This method allows subclasses to provide a way to access the ServletContext
//	 * according to the rendering technology.
//	 */
//	protected abstract ServletContext getServletContext();
//
//	/**
//	 * Make an authorization decision by considering all &lt;authorize&gt; tag attributes.
//	 * The following are valid combinations of attributes:
//	 * <ul>
//	 * <li>access</li>
//	 * <li>url, method</li>
//	 * </ul>
//	 * The above combinations are mutually exclusive and evaluated in the given order.
//	 *
//	 * @return the result of the authorization decision
//	 * @throws IOException
//	 */
//	public boolean authorize() throws IOException {
//		boolean isAuthorized;
//
//		if (StringUtils.hasText(getAccess())) {
//			isAuthorized = authorizeUsingAccessExpression();
//
//		}
//		else if (StringUtils.hasText(getUrl())) {
//			isAuthorized = authorizeUsingUrlCheck();
//
//		}
//		else {
//			isAuthorized = false;
//
//		}
//
//		return isAuthorized;
//	}
//
//	/**
//	 * Make an authorization decision based on a Spring EL expression. See the
//	 * "Expression-Based Access Control" chapter in Spring Security for details on what
//	 * expressions can be used.
//	 *
//	 * @return the result of the authorization decision
//	 * @throws IOException
//	 */
//	public boolean authorizeUsingAccessExpression() throws IOException {
//		if (SecurityContextHolder.getContext().getAuthentication() == null) {
//			return false;
//		}
//
//		SecurityExpressionHandler<FilterInvocation> handler = getExpressionHandler();
//
//		Expression accessExpression;
//		try {
//			accessExpression = handler.getExpressionParser().parseExpression(getAccess());
//
//		}
//		catch (ParseException e) {
//			IOException ioException = new IOException();
//			ioException.initCause(e);
//			throw ioException;
//		}
//
//		return ExpressionUtils.evaluateAsBoolean(accessExpression,
//				createExpressionEvaluationContext(handler));
//	}
//
//	/**
//	 * Allows the {@code EvaluationContext} to be customized for variable lookup etc.
//	 */
//	protected EvaluationContext createExpressionEvaluationContext(
//			SecurityExpressionHandler<FilterInvocation> handler) {
//		FilterInvocation f = new FilterInvocation(getRequest(), getResponse(),
//				new FilterChain() {
//					public void doFilter(ServletRequest request, ServletResponse response)
//							throws IOException, ServletException {
//						throw new UnsupportedOperationException();
//					}
//				});
//
//		return handler.createEvaluationContext(SecurityContextHolder.getContext()
//				.getAuthentication(), f);
//	}
//
//	/**
//	 * Make an authorization decision based on the URL and HTTP method attributes. True is
//	 * returned if the user is allowed to access the given URL as defined.
//	 *
//	 * @return the result of the authorization decision
//	 * @throws IOException
//	 */
//	public boolean authorizeUsingUrlCheck() throws IOException {
//		String contextPath = ((HttpServletRequest) getRequest()).getContextPath();
//		Authentication currentUser = SecurityContextHolder.getContext()
//				.getAuthentication();
//		return getPrivilegeEvaluator().isAllowed(contextPath, getUrl(), getMethod(),
//				currentUser);
//	}
//
//	public String getAccess() {
//		return access;
//	}
//
//	public void setAccess(String access) {
//		this.access = access;
//	}
//
//	public String getUrl() {
//		return url;
//	}
//
//	public void setUrl(String url) {
//		this.url = url;
//	}
//
//	public String getMethod() {
//		return method;
//	}
//
//	public void setMethod(String method) {
//		this.method = (method != null) ? method.toUpperCase() : null;
//	}
//
//	/*------------- Private helper methods  -----------------*/
//
//	@SuppressWarnings({ "unchecked", "rawtypes" })
//	private SecurityExpressionHandler<FilterInvocation> getExpressionHandler()
//			throws IOException {
//		// ApplicationContext appContext = SecurityWebApplicationContextUtils.findRequiredWebApplicationContext(getServletContext());
//
//		// 1.获取ServletContext对象
//		ServletContext servletContext = getServletContext();
//
//		// 2.拼接SpringMVC在ServletContext域中的属性名
//		String attrName = FrameworkServlet.SERVLET_CONTEXT_PREFIX + "springDispatcherServlet";
//
//		// 3.从ServletContext域中获取IOC容器对象
//		ApplicationContext appContext = (ApplicationContext) servletContext.getAttribute(attrName);
//
//		Map<String, SecurityExpressionHandler> handlers = appContext
//				.getBeansOfType(SecurityExpressionHandler.class);
//
//		for (SecurityExpressionHandler h : handlers.values()) {
//			if (FilterInvocation.class.equals(GenericTypeResolver.resolveTypeArgument(
//					h.getClass(), SecurityExpressionHandler.class))) {
//				return h;
//			}
//		}
//
//		throw new IOException(
//				"No visible WebSecurityExpressionHandler instance could be found in the application "
//						+ "context. There must be at least one in order to support expressions in JSP 'authorize' tags.");
//	}
//
//	private WebInvocationPrivilegeEvaluator getPrivilegeEvaluator() throws IOException {
//		WebInvocationPrivilegeEvaluator privEvaluatorFromRequest = (WebInvocationPrivilegeEvaluator) getRequest()
//				.getAttribute(WebAttributes.WEB_INVOCATION_PRIVILEGE_EVALUATOR_ATTRIBUTE);
//		if (privEvaluatorFromRequest != null) {
//			return privEvaluatorFromRequest;
//		}
//
//		ApplicationContext ctx = SecurityWebApplicationContextUtils.findRequiredWebApplicationContext(getServletContext());
//		Map<String, WebInvocationPrivilegeEvaluator> wipes = ctx
//				.getBeansOfType(WebInvocationPrivilegeEvaluator.class);
//
//		if (wipes.size() == 0) {
//			throw new IOException(
//					"No visible WebInvocationPrivilegeEvaluator instance could be found in the application "
//							+ "context. There must be at least one in order to support the use of URL access checks in 'authorize' tags.");
//		}
//
//		return (WebInvocationPrivilegeEvaluator) wipes.values().toArray()[0];
//	}
//}
